package com.taotao.tools.jackson.serializer;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.taotao.tools.jackson.annotations.Default2Null;
import com.taotao.tools.jackson.constant.DefaultValue;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Objects;

/**
 * 将特殊值转化为null.方便前端显示
 */
@AllArgsConstructor
@NoArgsConstructor
public class Default2NullSerializer extends JsonSerializer<Object> implements ContextualSerializer {

    private Default2Null anno;

    private JsonSerializer<Object> defalutSerializer;

    @Override
    public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider)
            throws IOException {

        if (null == value) {
            // 使用默认的序列化行为
            defalutSerializer.serialize(value, jgen, provider);
        }

        String nullValStr = anno.value().trim();

        String valueStr = value.toString().trim();

        // int/long/short 等及其包装类
        if (DefaultValue.int_class.contains(value.getClass())) {

            if (isBlank(nullValStr)) {
                nullValStr = DefaultValue.int_null;
            }


        } else if (DefaultValue.decimal_class.contains(value.getClass())) {


            if (isBlank(nullValStr)) {
                nullValStr = DefaultValue.decimal_null;
            }

            valueStr = trimZero(valueStr);

        } else if (value instanceof CharSequence) {
            if (isBlank(nullValStr)) {
                nullValStr = DefaultValue.string_null;
            }
        } else if (DefaultValue.date_class.contains(value.getClass())) {
            if (isBlank(nullValStr)) {
                nullValStr = DefaultValue.date_null;
            }

            valueStr = DateTimeFormatter.ofPattern(DefaultValue.date_parttern).format((LocalDate) value);
        } else if (DefaultValue.datetime_class.contains(value.getClass())) {
            if (isBlank(nullValStr)) {
                nullValStr = DefaultValue.datetime_null;
            }
            if (value instanceof Date) {
                SimpleDateFormat df = new SimpleDateFormat(DefaultValue.datetime_parttern);
                valueStr = df.format((Date) value);
            }
            if (value instanceof LocalDateTime) {
                valueStr = DateTimeFormatter.ofPattern(DefaultValue.datetime_parttern).format((LocalDateTime) value);
            }

        } else if (DefaultValue.localtime_class.contains(value.getClass())) {
            if (isBlank(nullValStr)) {
                nullValStr = DefaultValue.localtime_null;
            }
            valueStr = DateTimeFormatter.ofPattern(DefaultValue.localtime_parttern).format((LocalTime) value);
        }


        if (Objects.equals(nullValStr, valueStr)) {
            jgen.writeObject(null);
        } else {
            // 使用默认的序列化行为
            defalutSerializer.serialize(value, jgen, provider);
        }
    }


    @Override
    public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {

        if (beanProperty == null) {
            //为空直接跳过
            return serializerProvider.findNullValueSerializer(beanProperty);
        }

        Default2Null anno = beanProperty.getAnnotation(Default2Null.class);
        JsonSerializer<Object> defalut = serializerProvider.findContentValueSerializer(beanProperty.getType(), beanProperty);
        if (null == anno) {
            return defalut;
        }

        return new Default2NullSerializer(anno, defalut);
    }


    /**
     * 去掉数字末尾多余的零
     *
     * @param num
     * @return
     */
    public static String trimZero(String num) {
        if (num.indexOf(".") > 0) {
            num = num.replaceAll("0+?$", "");
            num = num.replaceAll("[.]$", "");

        }

        return num;
    }

    public static boolean isBlank(final CharSequence cs) {
        int strLen;
        if (cs == null || (strLen = cs.length()) == 0) {
            return true;
        }
        for (int i = 0; i < strLen; i++) {
            if (!Character.isWhitespace(cs.charAt(i))) {
                return false;
            }
        }
        return true;
    }

}